#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define TASK_NUM 5

typedef void (*task_t)();

///////////////////////////////////////////////////////////// 
void download()
{
    printf("this is a download task is runing!\n");
}
void printLog()
{
    printf("this is a write log task is runing!\n");
}
void show()
{
    printf("this is a show info task is runing!\n");
}
///////////////////////////////////////////////////////////// 


void initTasks(task_t tasks[], int num)
{
    for(int i = 0; i < num; i++) tasks[i]= NULL;
}

int addTask(task_t tasks[], task_t t)
{
    int i = 0;
    for(; i < TASK_NUM; i++) // 循环+判断将函数指针依次放入函数指针数组中
    {
        if(tasks[i] == NULL)
        {
            tasks[i] = t;
            return 1;
        }
    }
    return 0;
}

void executeTask(task_t tasks[], int num)
{
    for(int i = 0; i < num; i++)
    {
        if(tasks[i]) tasks[i]();
    }   
}

void worker(int cnt)
{
    printf("I am child process, pid: %d, ppid: %d, cnt: %d\n", getpid(), getppid(), cnt);
}
// waitpid第三个参数测试的单个子进程
int main()
{
    task_t tasks[TASK_NUM]; // 函数指针数组
    initTasks(tasks, TASK_NUM);
    addTask(tasks, download);
    addTask(tasks, printLog);
    addTask(tasks, show);

    pid_t id = fork();
    if(0 == id)
    {
        // child
        int cnt = 3;
        while(cnt)
        {
            worker(cnt);
            sleep(1);
            cnt--;
        }
        exit(0);
    }

    // father
    while(1)
    {
        int status = 0;
        // 非阻塞等待，可以让等待方在等待的时候，顺便做做自己的事情
        pid_t rid = waitpid(id, &status, WNOHANG);
        if(rid > 0)
        { //waitpid返回值大于0，等待成功
            printf("child quit success, exit code: %d, exit signal: %d\n", (status>>8)&0xFF, status&0x7F);
            break;
        }
        else if(rid == 0)
        {// 返回值等于0，等待成功，但是子进程没有退出，可以做占用时间少的事
            printf("####################################\n");
            printf("father do other thing...\n");
            // 该函数内部，其实是函数回调方式
            executeTask(tasks, TASK_NUM);
            printf("####################################\n");
            sleep(1);
        }
        else 
        {// 等待失败
            printf("wait failed!\n");
            break;
        }
    }
    return 0;
}


// 多个子进程
//const int n = 10;
//
//int main()
//{
//    for(int i = 0; i < n; i++)
//    {
//        pid_t id = fork();
//        if(0 == id)
//        {
//            // child
//            Worker(i);
//            exit(i);
//        }
//    }
//
//    // 等待多个子进程
//    for(int i = 0; i < n; i++)
//    {
//        int status = 0;
//        pid_t rid = waitpid(-1, &status, 0); // 那个进程被等待成功返回那个进程的pid
//        if(rid > 0)
//        {
//            printf("wait child %d success, exit code: %d\n", rid, WEXITSTATUS(status));
//        }
//    }
//
//    return 0;
//}


// 单个子进程
//int main()
//{
//    pid_t id = fork();
//    if(0 == id)
//    {
//        // child
//        Worker();
//        exit(1);
//    }
//    else 
//    {
//        //sleep(6); // 不会让父进程立即回收子进程
//        // father
//        printf("wait before\n");
//        //pid_t rid = wait(NULL);
//        int status = 0;
//        pid_t rid = waitpid(id, &status, 0);
//        printf("wait after\n");
//        if(rid == id)
//        {
//            //printf("wait success, pid: %d, rid: %d, exit sig: %d, exit code: %d\n", getpid(), rid, status&0x7F, (status>>8)&0xFF);
//            if(WIFEXITED(status))
//            {
//                printf("child process normal quit, exit code: %d\n", WEXITSTATUS(status));
//            }
//            else 
//            {
//                printf("child process quit except!\n");
//            }
//        }
//        sleep(2); // 最后只剩父进程跑
//    }
//    return 0;
//}

